home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / mewin10s.zip / MSWFILE.C < prev    next >
C/C++ Source or Header  |  1992-04-17  |  17KB  |  598 lines

  1. /* The routines in this file provide support for file access under the
  2.    Microsoft Windows environment on an IBM-PC or compatible computer.
  3.  
  4.    Must be compiled with Borland C++ 2.0 or later version.
  5.  
  6.    It should not be compiled if the WINDOW_MSWIN symbol is not set */
  7.  
  8. #include    "estruct.h"
  9. #include    <stdio.h>
  10. #include    <dir.h>
  11. #include    "eproto.h"
  12. #include    "edef.h"
  13. #if  TURBO
  14. #define malloc dummy_malloc
  15. #define realloc dummy_realloc
  16. #include    <stdlib.h>
  17. #undef malloc
  18. #undef realloc
  19.  
  20. struct ffblk fileblock;    /* structure for directory searches */
  21. #endif
  22. #if    MSC | ZTC
  23. #include <dos.h>
  24.  
  25. struct find_t fileblock;    /* structure for directory searches */
  26. #endif
  27.  
  28. #include    "mswin.h"
  29.  
  30. /* macros */
  31. #define ATTR_DIR    (0x4010 | 0x8000)   /* attributes for dir listbox */
  32. #define ATTR_FIL    (0x0021)            /* attributes for file listbox */
  33.  
  34. /* structures */
  35. typedef struct PARAMS {     /* parameters between filenamedlg and
  36.                    FileDlgProc (pointed by Par) */
  37.     char    Name [13];  /* file name */
  38.     char    *Prompt;    /* prompt text for the caption */
  39. } PARAMS;
  40.  
  41. /* static variables */
  42. static  char    Path [NFILEN] = "";    /* directory path */
  43. static  char    StarName [13] = "*.*";  /* starname */
  44. static  PARAMS  *Par;
  45.  
  46. /* function prototypes */
  47. int EXPORT far pascal FileDlgProc (HWND hDlg, WORD wMsg, WORD wParam,
  48.                                    DWORD lParam);
  49. static void near    CompletePath (char *s, char *FileName);
  50. static void near    UpdateAll (HWND hDlg, char *s);
  51.  
  52. /* ChangeWorkingDir:    sets the working dir to match the supplied path */
  53. /* ================                                                     */
  54.  
  55. static int near ChangeWorkingDir (char * FilePath)
  56.  
  57. /* returns 0 if successful, -1 otherwise */
  58. {
  59.     char    *WorkPath;
  60.     char    *Backslash; /* will find the last backslash in the path */
  61.     char    Crushed;
  62.     int     Result;
  63.  
  64.     WorkPath = FilePath;
  65.     if (*WorkPath == '\0') return 0;    /* empty path! */
  66.     if (WorkPath[1] == ':') {   /* drive specification */
  67.         int     disk;
  68.  
  69.     setdisk (disk = (tolower(*WorkPath) - 'a'));
  70.     if (disk != getdisk ()) return -1;
  71.     WorkPath += 2;  /* skip that drive spec */
  72.     }
  73.     
  74.     for (Backslash = WorkPath; *Backslash != '\0'; Backslash++) ;
  75.     while (*Backslash != '\\') {
  76.         if (Backslash == WorkPath) break;
  77.     --Backslash;
  78.     }
  79.     /* Backslash now points at the last backslash in the file path. That
  80.        is the end of the directory path */
  81.     if ((Backslash == WorkPath) && (*Backslash == '\\')) ++Backslash;
  82.     Crushed = *Backslash;
  83.     *Backslash = '\0';      /* temporarily terminate the path there */
  84.     if (*WorkPath == '\0') Result = TRUE;
  85.     else Result = chdir (WorkPath);
  86.     *Backslash = Crushed;   /* restore the file path before returning */
  87.     return Result;
  88. } /* ChangeWorkingDir */
  89.  
  90. /* SetWorkingDir:   sets the working dir to the current window's path */
  91. /* =============                                                      */
  92.  
  93. int far pascal SetWorkingDir (void)
  94.  
  95. /* returns 0 if successful, -1 otherwise */
  96. /* this function also sets the text of the Path displayed in the FILE
  97.    dialog */
  98. {
  99.     int     Result;
  100.  
  101.     Result = ChangeWorkingDir (curbp->b_fname);
  102.     if (Result == 0) getcwd (Path, NFILEN);
  103.     return Result;
  104. } /* SetWorkingDir */
  105.  
  106. /* fullpathname:    fully qualifies the given pathname */
  107. /* ============                                        */
  108.  
  109. char * pascal   fullpathname (char *PathName, int Nbuf)
  110.  
  111. /* the PathName argument is assumed to be at least Nbuf characters
  112.    long. It is modified to contain the corresponding full pathname. The
  113.    returned address is the PathName argument. */
  114. {
  115.     char    FullName [_MAX_PATH];
  116.  
  117.     if (_fullpath(FullName, PathName, Nbuf) != NULL) {
  118.         strcpy (PathName, FullName);
  119.     }
  120.     return PathName;
  121. } /* fullpathname */
  122.  
  123. /* filenamedlg: equivalent of mlreply, but specifically to get a filename */
  124. /* ===========                                                            */
  125.  
  126. PASCAL  filenamedlg (char *prompt, char *buf, int nbuf, int fullpath)
  127. {
  128.     PARAMS  Parameters;
  129.     FARPROC ProcInstance;
  130.     BOOL    Result;
  131.  
  132.     SetWorkingDir ();
  133.     if (clexec || (kbdmode != STOP)) {  /* not interactive */
  134.         Result = mlreply (prompt, buf, nbuf);
  135.         if (Result == TRUE) {
  136.         if (fullpath) fullpathname (buf, nbuf);
  137.         }
  138.         return Result;
  139.     }
  140.     Parameters.Prompt = prompt;
  141.     Par = &Parameters;
  142.     ProcInstance = MakeProcInstance ((FARPROC)FileDlgProc, hEmacsInstance);
  143.     if (Result = (DialogBox (hEmacsInstance, "FILE", hFrameWnd,
  144.                              ProcInstance) >= 0)) {
  145.         CompletePath (buf, Parameters.Name);
  146.     }
  147.     FreeProcInstance (ProcInstance);
  148.     SetWorkingDir ();
  149.     return Result;
  150. } /* filenamedlg */
  151.  
  152. /* FileDlgOK:   process OK in File Dialog */
  153. /* =========                              */
  154.  
  155. static BOOL pascal near FileDlgOK (HWND hDlg)
  156.  
  157. /* this is a service function for FileDlgProc. It processes the OK case.
  158.    The returned value is TRUE if the dialog box is ending, FALSE
  159.    otherwise */
  160. {
  161.     char    s [NFILEN];
  162.  
  163.     GetDlgItemText (hDlg, ID_FILENAME, s, NFILEN);
  164.     if (*s == 0) return FALSE;  /* empty name, ignore it! */
  165.     if (strchr (s, '*') || strchr (s, '?')) {
  166.     /* there is a starname here! */
  167.     UpdateAll (hDlg, s);
  168.     }
  169.     else {
  170.     int     l;
  171.     char    *n;
  172.  
  173.     l = strlen (s);
  174.     n = &s[l - 1];
  175.     if ((*n == '\\') || (*n == ':')) {
  176.         /* it is a directory or drive */
  177.         if (l < NFILEN - 13) {
  178.         strcat (s, StarName);
  179.         UpdateAll (hDlg, s);
  180.         }
  181.     }
  182.     else {
  183.         /* it looks like a bonafide file name ! */
  184.         int     nl = 1;
  185.  
  186.         /* first, we extract the filename portion...*/
  187.         do {
  188.         if (n-- == &s[0]) goto ExtractedOK;
  189.         if ((*n == ':') || (*n == '\\')) goto ExtractedOK;
  190.         } while (++nl < 13);
  191.         return FALSE;
  192. ExtractedOK:
  193.         strcpy (Par->Name, ++n);
  194.         if (&s[0] - n < NFILEN - 13) {
  195.         strcpy (n, StarName);
  196.         /* now, we use DlgDirList to generate the full directory
  197.            path */
  198.         if (DlgDirList (hDlg, s, NULL, ID_PATH, ATTR_FIL)) {
  199.             GetDlgItemText (hDlg, ID_PATH, Path, NFILEN);
  200.             EndDialog (hDlg, 0);
  201.             return TRUE;
  202.         }
  203.         }
  204.     }
  205.     }
  206.     return FALSE;
  207. } /* FileDlgOK */
  208.  
  209. /* FileNameCompletion:  process filename edit box for name completion */
  210. /* ==================                                                 */
  211.  
  212. /* scrolls the file list box to bring the first match into view and
  213.    attempt filename completion if a space is placed at the end of the
  214.    edit field. Returns TRUE if filename completion was attempted and
  215.    successful, FALSE otherwise. */
  216. static BOOL pascal near FileNameCompletion (HWND hDlg)
  217. {
  218.     char    s [NFILEN];
  219.     int     i;
  220.     BOOL    PleaseComplete = FALSE;
  221.  
  222.     i = GetDlgItemText (hDlg, ID_FILENAME, s, NFILEN);
  223.     while ((i > 0) && (s[--i] == ' ')) {
  224.     PleaseComplete = TRUE;
  225.     s[i] = '\0';
  226.     }
  227.     if (PleaseComplete) {
  228.     DWORD   LastSel;
  229.  
  230.     LastSel = SendDlgItemMessage (hDlg, ID_FILENAME, EM_GETSEL, 0, 0L);
  231.         SetDlgItemText (hDlg, ID_FILENAME, s);  /* remove the spaces */
  232.         SendDlgItemMessage (hDlg, ID_FILENAME, EM_SETSEL, 0, LastSel);
  233.     }
  234.     if (strchr (s, '\\') || strchr (s, ':') || strchr (s, '[')) {
  235.         return FALSE;   /* contains more than a plain file name. The
  236.                file list box will not be appropriate for
  237.                completion so we do not attempt anything */
  238.     }
  239.     i = LOWORD(SendDlgItemMessage (hDlg, ID_FILES, LB_SELECTSTRING,
  240.                                    -1, (DWORD)(LPSTR)&s[0]));
  241.     if (i == LB_ERR) {
  242.         /* no match, give up! */
  243.         return FALSE;
  244.     }
  245.     SendDlgItemMessage (hDlg, ID_FILES, LB_SETTOPINDEX, i, 0L);
  246.     if (PleaseComplete) {
  247.         if (i != LOWORD(SendDlgItemMessage (hDlg, ID_FILES, LB_FINDSTRING,
  248.                                             i, (DWORD)(LPSTR)&s[0]))) {
  249.             return FALSE;   /* not unique ==> completion fails */
  250.         }
  251.         else {
  252.             SendDlgItemMessage (hDlg, ID_FILES, LB_GETTEXT,
  253.                                 i, (DWORD)(LPSTR)&s[0]);
  254.             SetDlgItemText (hDlg, ID_FILENAME, s);
  255.             return TRUE;
  256.         }
  257.     }
  258.     return FALSE;
  259. } /* FileNameCompletion */
  260.  
  261. /* FileDlgProc: Open file dialog function */
  262. /* ===========                            */
  263. int EXPORT far pascal  FileDlgProc (HWND hDlg, WORD wMsg, WORD wParam,
  264.                                     DWORD lParam)
  265. {
  266.     char    s [NFILEN];    /* all purpose */
  267.     int     i;
  268.     
  269.     switch (wMsg) {
  270.         
  271.     case WM_INITDIALOG:
  272.     {   /* let's build the caption */
  273.         char    DlgTitle [sizeof(PROGNAME) + 3 + 30];
  274.  
  275.         strcpy (DlgTitle, ProgName);
  276.         strcat (DlgTitle, " - ");
  277.         strcat (DlgTitle, Par->Prompt); /* hopefully, the prompt is
  278.                            under 30 char! */
  279.         i = strlen (DlgTitle) - 1;
  280.         while (DlgTitle[i] == ' ') i--;
  281.         if (DlgTitle[i] == ':') DlgTitle[i] = 0;
  282.             /* we remove the colon+spaces at the end of the prompt */
  283.         SetWindowText (hDlg, DlgTitle);
  284.     }
  285.     SetFocus (GetDlgItem (hDlg, ID_FILENAME));
  286.         CompletePath (s, StarName);
  287.         UpdateAll (hDlg, s);
  288.         i = 0;
  289.         while (in_check()) {
  290.             /* we need to send to the dialog box the characters stored
  291.            into the in_put() buffer. For instance, if the user typed
  292.            ^X^F while the startup script was running (to specify the
  293.            first file to read in) and quickly followed this by
  294.            typing a file name. The Find file dialog box would not
  295.            receive those characters which would already have been
  296.            absorbed into the in_put() pipe and would later end up
  297.            inserted at the beginning of the buffer! */
  298.         int     c;
  299.  
  300.         c = in_get();
  301.         switch (c) {
  302.         case 0: /* escape sequence, discard it... */
  303.             if (in_get() & (MOUS >> 8)) {
  304.                 in_get();
  305.                 in_get();
  306.             }
  307.             in_get();
  308.             break;
  309.         case '\b':  /* backspace */
  310.         if (i > 0) i--;
  311.         break;
  312.         case '\r':  /* Enter */
  313.         s[i] = '\0';
  314.         SetDlgItemText (hDlg, ID_FILENAME, s);
  315.         if (FileDlgOK (hDlg)) goto NoMoreTypeAhead;
  316.         break;
  317.         case 0x1B:  /* Escape */
  318.             EndDialog (hDlg, -1);
  319.         goto NoMoreTypeAhead;
  320.         default:
  321.             if ((c > 0x1F) && (c < 0x7F)) {
  322.                 /* regular ASCII char, stuff it into the filename */
  323.                 s[i++] = c;
  324.             }
  325.             /* else, discard it */
  326.             break;
  327.         }
  328.     }
  329.         if (i > 0) {
  330.             s[i] = '\0';
  331.         SetDlgItemText (hDlg, ID_FILENAME, s);
  332.         SendDlgItemMessage (hDlg, ID_FILENAME, EM_SETSEL, 0,
  333.                             MAKELONG(i, i));
  334.     }
  335.     else {
  336.         SendDlgItemMessage (hDlg, ID_FILENAME, EM_SETSEL, 0,
  337.                             MAKELONG(0, 32767));
  338.     }
  339.     if (FileNameCompletion (hDlg)) FileDlgOK (hDlg);
  340. NoMoreTypeAhead:
  341.     return FALSE;
  342.     
  343.     case WM_COMMAND:
  344.     switch (wParam) {
  345.  
  346.     case ID_FILENAME:
  347.         if (HIWORD(lParam) == EN_CHANGE) {
  348.             if (FileNameCompletion (hDlg)) FileDlgOK (hDlg);
  349.         }
  350.         break;
  351.         
  352.     case ID_DIRECTORIES:
  353.         switch (HIWORD(lParam)) {
  354.         case LBN_SELCHANGE:
  355.         DlgDirSelect (hDlg, s, ID_DIRECTORIES);
  356.         strcat (s, StarName);
  357.         SetDlgItemText (hDlg, ID_FILENAME, s);
  358.         break;
  359.         case LBN_DBLCLK:
  360.         FileDlgOK (hDlg);   /* same as OK */
  361.         }
  362.         break;
  363.         
  364.     case ID_FILES:
  365.         switch (HIWORD(lParam)) {
  366.         case LBN_SELCHANGE:
  367.             DlgDirSelect (hDlg, s, ID_FILES);
  368.         i = strlen (s) - 1;
  369.         if (s[i] == '.') s[i] = 0;  /* zap dot at end of file
  370.                            name */
  371.             SetDlgItemText (hDlg, ID_FILENAME, s);
  372.         break;
  373.         case LBN_DBLCLK:
  374.         FileDlgOK (hDlg);   /* same as OK */
  375.         }
  376.         break;
  377.         
  378.     case IDOK:
  379.             FileDlgOK (hDlg);
  380.         break;
  381.         
  382.     case IDCANCEL:
  383.         EndDialog (hDlg, -1);
  384.         break;
  385.     }
  386.     break;
  387.     
  388.     default:
  389.     return FALSE;
  390.     }
  391.     return FALSE;
  392. } /* FileDlgProc */
  393.  
  394. /* CompletePath:  prepend Path to the FileName, result in s */
  395. /* ============                                             */
  396.  
  397. static void near    CompletePath (char *s, char *FileName)
  398.  
  399. /* s must be at least NFILEN characters long, while the length of Path +
  400.    the length of FileName must be < NFILEN */
  401. {
  402.     strcpy (s, Path);
  403.     if ((*s != 0) && (s[strlen (s) - 1] != '\\')) strcat (s, "\\");
  404.     strcat (s, FileName);
  405. } /* CompletePath */
  406.  
  407. /* UpdateAll:   updates all the controls from the path in s */
  408. /* =========                                                */
  409.  
  410. static void near    UpdateAll (HWND hDlg, char *s)
  411.  
  412. /* this function also keeps the static variables Path and StarName up to
  413.    date */
  414. {
  415.     if (DlgDirList (hDlg, s, ID_DIRECTORIES, ID_PATH, ATTR_DIR)) {
  416.         GetDlgItemText (hDlg, ID_PATH, Path, NFILEN);
  417.         strcpy (StarName, s);
  418.     DlgDirList (hDlg, s, ID_FILES, NULL, ATTR_FIL);
  419.         SetDlgItemText (hDlg, ID_FILENAME, StarName);
  420.     SendDlgItemMessage (hDlg, ID_FILENAME, EM_SETSEL, 0,
  421.                         MAKELONG(0, 32767));
  422.     }
  423. } /* UpdateAll */
  424.  
  425. #if    TURBO
  426. /*    FILE Directory routines        */
  427. /* all borrowed from MSDOS.C */
  428.  
  429. char path[NFILEN];    /* path of file to find */
  430. char rbuf[NFILEN];    /* return file buffer */
  431.  
  432. /*    do a wild card directory search (for file name completion) */
  433.  
  434. char *pascal getffile(fspec)
  435.  
  436. char *fspec;    /* pattern to match */
  437.  
  438. {
  439.     register int index;        /* index into various strings */
  440.     register int point;        /* index into other strings */
  441.     register int extflag;        /* does the file have an extention? */
  442.     char fname[NFILEN];        /* file/path for DOS call */
  443.  
  444.     /* first parse the file path off the file spec */
  445.     strcpy(path, fspec);
  446.     index = strlen(path) - 1;
  447.     while (index >= 0 && (path[index] != '/' &&
  448.                 path[index] != '\\' && path[index] != ':'))
  449.         --index;
  450.     path[index+1] = 0;
  451.  
  452.     /* check for an extension */
  453.     point = strlen(fspec) - 1;
  454.     extflag = FALSE;
  455.     while (point > index) {
  456.         if (fspec[point] == '.') {
  457.             extflag = TRUE;
  458.             break;
  459.         }
  460.         point--;
  461.     }
  462.  
  463.     /* construct the composite wild card spec */
  464.     strcpy(fname, path);
  465.     strcat(fname, &fspec[index+1]);
  466.     strcat(fname, "*");
  467.     if (extflag == FALSE)
  468.         strcat(fname, ".*");
  469.  
  470.     /* and call for the first file */
  471.     if (findfirst(fname, &fileblock, FA_DIREC) == -1)
  472.         return(NULL);
  473.  
  474.     /* return the first file name! */
  475.     strcpy(rbuf, path);
  476.     strcat(rbuf, fileblock.ff_name);
  477.     mklower(rbuf);
  478.     if (fileblock.ff_attrib == 16)
  479.         strcat(rbuf, DIRSEPSTR);
  480.     return(rbuf);
  481. }
  482.  
  483. char *pascal getnfile()
  484.  
  485. {
  486.     register int index;        /* index into various strings */
  487.     register int point;        /* index into other strings */
  488.     register int extflag;        /* does the file have an extention? */
  489.     char fname[NFILEN];        /* file/path for DOS call */
  490.  
  491.     /* and call for the first file */
  492.     if (findnext(&fileblock) == -1)
  493.         return(NULL);
  494.  
  495.     /* return the first file name! */
  496.     strcpy(rbuf, path);
  497.     strcat(rbuf, fileblock.ff_name);
  498.     mklower(rbuf);
  499.     if (fileblock.ff_attrib == 16)
  500.         strcat(rbuf, DIRSEPSTR);
  501.     return(rbuf);
  502. }
  503. #else
  504. #if    MSC | ZTC
  505. /*    FILE Directory routines        */
  506.  
  507. char path[NFILEN];    /* path of file to find */
  508. char rbuf[NFILEN];    /* return file buffer */
  509.  
  510. /*    do a wild card directory search (for file name completion) */
  511.  
  512. char *pascal getffile(fspec)
  513.  
  514. char *fspec;    /* pattern to match */
  515.  
  516. {
  517.     register int index;        /* index into various strings */
  518.     register int point;        /* index into other strings */
  519.     register int extflag;        /* does the file have an extention? */
  520.     char fname[NFILEN];        /* file/path for DOS call */
  521.  
  522.     /* first parse the file path off the file spec */
  523.     strcpy(path, fspec);
  524.     index = strlen(path) - 1;
  525.     while (index >= 0 && (path[index] != '/' &&
  526.                 path[index] != '\\' && path[index] != ':'))
  527.         --index;
  528.     path[index+1] = 0;
  529.  
  530.     /* check for an extension */
  531.     point = strlen(fspec) - 1;
  532.     extflag = FALSE;
  533.     while (point > index) {
  534.         if (fspec[point] == '.') {
  535.             extflag = TRUE;
  536.             break;
  537.         }
  538.         point--;
  539.     }
  540.  
  541.     /* construct the composite wild card spec */
  542.     strcpy(fname, path);
  543.     strcat(fname, &fspec[index+1]);
  544.     strcat(fname, "*");
  545.     if (extflag == FALSE)
  546.         strcat(fname, ".*");
  547.  
  548.     /* and call for the first file */
  549.     if (_dos_findfirst(fname, _A_NORMAL|_A_SUBDIR, &fileblock) != 0)
  550.         return(NULL);
  551.  
  552.     /* return the first file name! */
  553.     strcpy(rbuf, path);
  554.     strcat(rbuf, fileblock.name);
  555.     mklower(rbuf);
  556.     if (fileblock.attrib == 16)
  557.         strcat(rbuf, DIRSEPSTR);
  558.     return(rbuf);
  559. }
  560.  
  561. char *pascal getnfile()
  562.  
  563. {
  564.     register int index;        /* index into various strings */
  565.     register int point;        /* index into other strings */
  566.     register int extflag;        /* does the file have an extention? */
  567.     char fname[NFILEN];        /* file/path for DOS call */
  568.  
  569.     /* and call for the first file */
  570.     if (_dos_findnext(&fileblock) != 0)
  571.         return(NULL);
  572.  
  573.     /* return the first file name! */
  574.     strcpy(rbuf, path);
  575.     strcat(rbuf, fileblock.name);
  576.     mklower(rbuf);
  577.     if (fileblock.attrib == 16)
  578.         strcat(rbuf, DIRSEPSTR);
  579.     return(rbuf);
  580. }
  581. #else
  582. char *pascal getffile(fspec)
  583.  
  584. char *fspec;    /* file to match */
  585.  
  586. {
  587.     return(NULL);
  588. }
  589.  
  590. char *pascal getnfile()
  591.  
  592. {
  593.     return(NULL);
  594. }
  595. #endif
  596. #endif
  597.  
  598.